package avicit.bdp.dms.prm.Integration;

import avicit.bdp.common.base.BaseDAO;
import avicit.bdp.common.service.dto.BdpColumnDTO;
import avicit.bdp.common.service.dto.BdpTableDTO;
import avicit.bdp.common.utils.DateUtils;
import avicit.bdp.common.utils.SpringApplicationContext;
import avicit.bdp.dms.das.dao.BdpDasCategoryDao;
import avicit.bdp.dms.das.dao.BdpDasColumnDao;
import avicit.bdp.dms.das.dao.BdpDasTableDao;
import avicit.bdp.dms.das.dto.BdpDasCategoryDTO;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 模型消息处理
 *
 * @author xugb
 * @date 2021/11/4 17:56
 */

public class TableHandle extends BaseMessageHandle {
    private static final Logger log = LoggerFactory.getLogger(TableHandle.class);

    private BdpDasTableDao dao;

    private BdpDasColumnDao columnDao;

    private BdpDasCategoryDao bdpDasCategoryDao;

    public static final String DEFAULT_TYPE_ID = "402891a4763fe3770176404c90f11164";

    public TableHandle() {
        dao = SpringApplicationContext.getBean(BdpDasTableDao.class);
        columnDao = SpringApplicationContext.getBean(BdpDasColumnDao.class);
        bdpDasCategoryDao = SpringApplicationContext.getBean(BdpDasCategoryDao.class);
    }

    public void excuteDelete(List<Map<String, Object>> list) {
        for (Map<String, Object> map : list) {
            String id = MapUtils.getString(map, "id");
            dao.deleteByPrimaryKey(id);
            BdpColumnDTO query = new BdpColumnDTO();
            query.setTableId(id);
            columnDao.delete(query);
        }
    }

    @Override
    public void excuteUpdate(List<Map<String, Object>> list) {
        for (Map<String, Object> map : list) {
            BdpTableDTO dto = convertDto(map);
            dao.updateByPrimaryKey(dto);
            List<Map<String, Object>> columnList = (List<Map<String, Object>>) MapUtils.getObject(map, "columnList");
            insertOrUpdateColumn(dto.getId(), columnList);
        }
    }

    private void insertOrUpdateColumn(String tableId, List<Map<String, Object>> columnList) {
        List<String> tableIdList = new ArrayList<>();
        tableIdList.add(tableId);
        List<BdpColumnDTO> oldList = columnDao.selectColumnList(tableIdList);

        for (Map<String, Object> columnMap : columnList) {
            BdpColumnDTO columnDTO = convertColumnDto(columnMap);
            BdpColumnDTO oldDto = columnDao.selectByPrimaryKey(columnDTO.getId());
            if (oldDto == null) {
                columnDao.insert(columnDTO);
            } else {
                columnDao.updateByPrimaryKey(columnDTO);
                removeList(oldList, columnDTO.getId());
            }
        }
        //删除的列
        for (BdpColumnDTO dto : oldList) {
            columnDao.deleteByPrimaryKey(dto.getId());
        }
    }

    private void removeList(List<BdpColumnDTO> oldList, String id) {
        for (BdpColumnDTO dto : oldList) {
            if (dto.getId().equals(id)) {
                oldList.remove(dto);
                break;
            }
        }
    }

    @Override
    public void excuteInsert(List<Map<String, Object>> list) {
        for (Map<String, Object> map : list) {
            BdpTableDTO dto = convertDto(map);
            BdpTableDTO oldDto = dao.selectByPrimaryKey(dto.getId());
            if (oldDto != null) {
                dao.updateByPrimaryKey(dto);
                List<Map<String, Object>> columnList = (List<Map<String, Object>>) MapUtils.getObject(map, "columnList");
                insertOrUpdateColumn(dto.getId(), columnList);

            } else {
                dao.insert(dto);
                List<Map<String, Object>> columnList = (List<Map<String, Object>>) MapUtils.getObject(map, "columnList");
                List<BdpColumnDTO> clist = new ArrayList<>();
                for (Map<String, Object> columnMap : columnList) {
                    BdpColumnDTO columnDTO = convertColumnDto(columnMap);
                    clist.add(columnDTO);
                }
                columnDao.insertListByBatch(clist);
            }

        }
    }

    private BdpColumnDTO convertColumnDto(Map<String, Object> map) {
        String id = MapUtils.getString(map, "id");
        String name = MapUtils.getString(map, "name");
        String cnName = MapUtils.getString(map, "cn_name");
        String columnType = MapUtils.getString(map, "column_type");
        Integer columnLength = MapUtils.getInteger(map, "column_length");
        Integer columnPrecision = MapUtils.getInteger(map, "column_precision");
        Integer nullable = MapUtils.getInteger(map, "nullable");
        Integer primaryKey = MapUtils.getInteger(map, "primaryKey");
        Integer uniqueKey = MapUtils.getInteger(map, "uniqueKey");
        Integer modifyable = MapUtils.getInteger(map, "modifyable");
        String tableId = MapUtils.getString(map, "table_id");
        Integer orderBy = MapUtils.getInteger(map, "order_by");
        String remark = MapUtils.getString(map, "remark");
        String createdBy = MapUtils.getString(map, "created_by");
        if(StringUtils.isBlank(createdBy)) {
            createdBy = "1";
        }
        String creationDate = MapUtils.getString(map, "creation_date");
        String lastUpdatedBy = MapUtils.getString(map, "last_updated_by");
        String lastUpdateDate = MapUtils.getString(map, "last_update_date");
        BdpColumnDTO dto = new BdpColumnDTO();
        dto.setId(id);
        dto.setName(name);
        dto.setCnName(cnName);
        dto.setColumnType(columnType);
        dto.setColumnLength(columnLength);
        dto.setColumnPrecision(columnPrecision);
        dto.setNullable(nullable);
        dto.setPrimaryKey(primaryKey);
        dto.setUniqueKey(uniqueKey);
        dto.setModifyable(modifyable);
        dto.setTableId(tableId);
        dto.setOrderBy(orderBy);
        dto.setRemark(remark);
        dto.setCreatedBy(createdBy);
        dto.setCreationDate(DateUtils.stringToDate(creationDate));
        dto.setLastUpdatedBy(lastUpdatedBy);
        dto.setLastUpdateDate(DateUtils.stringToDate(lastUpdateDate));
        return dto;
    }

    private BdpTableDTO convertDto(Map<String, Object> map) {
        String id = MapUtils.getString(map, "id");
        String name = MapUtils.getString(map, "name");
        String cnName = MapUtils.getString(map, "cn_name");
        String typeId = MapUtils.getString(map, "type_id");
        if(StringUtils.isBlank(typeId)){
            BdpDasCategoryDTO bdpDasCategoryDTO = bdpDasCategoryDao.selectByPrimaryKey(DEFAULT_TYPE_ID);
            if(bdpDasCategoryDTO == null){
                this.insertDefaultType();
            }
            typeId = DEFAULT_TYPE_ID;
        }else {
            BdpDasCategoryDTO bdpDasCategoryDTO = bdpDasCategoryDao.selectByPrimaryKey(typeId);
            if(bdpDasCategoryDTO == null || "0".equals(typeId)){
                BdpDasCategoryDTO categoryDTO = bdpDasCategoryDao.selectByPrimaryKey(DEFAULT_TYPE_ID);
                if(categoryDTO == null){
                    this.insertDefaultType();
                }
                typeId = DEFAULT_TYPE_ID;
            }
        }
        Integer type = MapUtils.getInteger(map, "type");
        String datasourceId = MapUtils.getString(map, "datasource_id");
        Integer storeStatus = MapUtils.getInteger(map, "store_status",1);
        String datasourceType = MapUtils.getString(map, "datasource_type");
        String storageGroup = MapUtils.getString(map, "storage_group");
        String dataStorageFormat = MapUtils.getString(map, "data_storage_format");
        String remark = MapUtils.getString(map, "remark");
        String createdBy = MapUtils.getString(map, "created_by");
        if(StringUtils.isBlank(createdBy)) {
            createdBy = "1";
        }
        String creationDate = MapUtils.getString(map, "creation_date");
        String lastUpdatedBy = MapUtils.getString(map, "last_updated_by");
        String lastUpdateDate = MapUtils.getString(map, "last_update_date");
        BdpTableDTO dto = new BdpTableDTO();
        dto.setId(id);
        dto.setName(name);
        dto.setCnName(cnName);
        dto.setTypeId(typeId);
        dto.setType(type);
        dto.setDataSourceId(datasourceId);
        dto.setStoreStatus(storeStatus);
        dto.setDataSourceType(datasourceType);
        dto.setStorageGroup(storageGroup);
        dto.setDataStorageFormat(dataStorageFormat);
        dto.setRemark(remark);
        dto.setCreatedBy(createdBy);
        dto.setCreationDate(DateUtils.stringToDate(creationDate));
        dto.setLastUpdatedBy(lastUpdatedBy);
        dto.setLastUpdateDate(DateUtils.stringToDate(lastUpdateDate));
        return dto;
    }

    private void insertDefaultType() {
        BdpDasCategoryDTO categoryDTO = new BdpDasCategoryDTO();
        categoryDTO.setId(DEFAULT_TYPE_ID);
        categoryDTO.setParentId("0");
        categoryDTO.setName("默认分类");
        categoryDTO.setLeaf(1);
        categoryDTO.setOrderBy(99);
        bdpDasCategoryDao.insert(categoryDTO);
    }

    public BaseDAO getDAO() {
        return this.dao;
    }


    @Override
    public String getType() {
        return "table";
    }

}
